package org.deri.odhd.buses.index;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.SimpleFSDirectory;
import org.deri.odhd.buses.model.Company;
import org.deri.odhd.buses.model.Journey;
import org.deri.odhd.buses.model.Stop;

public class Indexer {

	private static final int MAXIMUM_HITS = 100;
	
	private IndexWriter writer;
	private IndexSearcher searcher;

	private Directory _directory;
	
	public Indexer()throws IOException{
		_directory = new SimpleFSDirectory(new File("C:/luceneIndex"));
//		writer = new IndexWriter(_directory, new SimpleAnalyzer(), IndexWriter.MaxFieldLength.LIMITED);
		searcher = new IndexSearcher(_directory);	
	}
	
	public void indexJourneys(Set<Journey> journeys) throws CorruptIndexException, IOException {
		for(Journey j:journeys){
			Document doc = new Document();
			doc.add(new Field("journeyId", j.getId(), Field.Store.YES,Field.Index.NO));
			doc.add(new Field("companyName", j.getCompany().getName(), Field.Store.YES,Field.Index.NOT_ANALYZED));
			doc.add(new Field("day", j.getDay(), Field.Store.YES, Field.Index.NOT_ANALYZED));
			StringBuilder stopsNames = new StringBuilder();
			for(Stop stop:j.getStops()){
				stopsNames.append(stop.getName()).append(" ");
			}
			doc.add(new Field("stops", stopsNames.toString(), Field.Store.NO, Field.Index.ANALYZED));
			
			writer.addDocument(doc);
		}
		
		writer.close();
		
		searcher = new IndexSearcher(_directory);
	}

	public List<String> search(String day, String from, String to) throws IOException{
		Query query = buildQuery(day,from,to);
		TopDocs docs = searcher.search(query, MAXIMUM_HITS);
		return wrap(docs);
	}
	
	public List<Journey> searchJourneys(String day, String from, String to) throws IOException{
		Query query = buildQuery(day,from,to);
		TopDocs docs = searcher.search(query, MAXIMUM_HITS);
		return wrapJourneys(docs);
	}
	
	private Query buildQuery(String day, String from, String to){
		BooleanQuery q1 = new BooleanQuery();
		//q1.add(new TermQuery(new Term("projectId",GLOBAL_VOCABULARY_PLACE_HOLDER)), Occur.SHOULD);
		q1.add(new TermQuery(new Term("day",day)), Occur.MUST);
//		q1.add(new TermQuery(new Term("stops",from)), Occur.MUST);
//		q1.add(new TermQuery(new Term("stops",to)), Occur.MUST);
		
		return q1;
	}
	
	private List<String> wrap(TopDocs docs) throws CorruptIndexException, IOException{
		List<String> ids = new ArrayList<String>();
		for (int i = 0; i < docs.totalHits; i++) {
			Document doc = searcher.doc(docs.scoreDocs[i].doc);
			String journeyId = doc.get("journeyId");
			ids.add(journeyId);
		}
		return ids;
	}
	
	private List<Journey> wrapJourneys(TopDocs docs) throws CorruptIndexException, IOException{
		List<Journey> journeys = new ArrayList<Journey>();
		for (int i = 0; i < docs.totalHits; i++) {
			Document doc = searcher.doc(docs.scoreDocs[i].doc);
			String journeyId = doc.get("journeyId");
			String day = doc.get("day");
			String companyName = doc.get("companyName");
			
			Company company = new Company(companyName,null);
			Journey j = new Journey(journeyId, day, company, null); 
			
			journeys.add(j);
		}
		return journeys;
	}
}
